import { v4 as uuidv4 } from 'uuid';
type ReportDataType = {
  type: string;
  subType: string;
  pageUrl?: string; 
  startTime?: number;
  msg?: string | Event;
  url?: string;
  from?: string;
  to?: string;
  stack?: string;
  uuid?: string;
  lineNo?: number;
  columnNo?: number;
}
type ObserverConfig = {
  url: string;
  batchSize: number;
}
export class BaseObserver {
  private cache: ReportDataType[] = [];
  private analyticsQueue: string[] = [];
  private config: ObserverConfig = {
      batchSize: 10,
      url: 'http://127.0.0.1:8080'
  }
  constructor(config?: ObserverConfig) {
      this.config = {
          ...config,
          ...this.config
      }
      this.processAnalyticsQueue = this.processAnalyticsQueue.bind(this);
  }
  public getCache() {
      return this.cache;
  }
  public addCache(data: ReportDataType) {
      this.cache.push(data);
  }
  public clearCache() {
      this.cache.length = 0; 
  }
  public report(data: ReportDataType) {
      if (!this.config.url) {
          console.error('请设置上传 url 地址');
      }
      if (!this.analyticsQueue) this.analyticsQueue = [];
      const reportData = JSON.stringify({
          id: uuidv4(),
          data,
      });
      // 安排到浏览器主线程的空闲时段执行
      this.analyticsQueue.push(reportData);
      requestIdleCallback((deadline) => this.processAnalyticsQueue(deadline));
  }
  // biome-ignore lint/suspicious/noExplicitAny: <explanation>
  public processAnalyticsQueue(deadline: { timeRemaining: () => number; didTimeout: any; }) {
    while (
        this.analyticsQueue.length > 0 &&
        (deadline.timeRemaining() > 0 || deadline.didTimeout)
      ) {
        const data = this.analyticsQueue.shift() || '';
        // 上报数据，使用图片的方式
        this.imgRequest(data);
        }
    
      // 如果队列未清空，继续注册回调
      if (this.analyticsQueue.length > 0) {
        requestIdleCallback((deadline) => this.processAnalyticsQueue(deadline));
      }
  }
  public imgRequest(data: string) {
      const img = new Image();
      img.src = `${this.config.url}?data=${encodeURIComponent(JSON.stringify(data))}`;
  }
  // 安排到浏览器主线程的空闲时段执行
  public lazyReportBatch(data: ReportDataType) {
      this.addCache(data);
      // 应使用requestIdleCallback优化请求，防止阻塞主线程
      const dataCache = this.getCache();
      if (dataCache.length && dataCache.length > this.config.batchSize) {
        for(const key in dataCache) {
          this.report(dataCache[key]);
        }
        this.clearCache();
      }
  }
}